阅读更多

2顶
3踩

研发管理

转载新闻 给代码多留一些空间

2014-06-09 10:20 by 正式记者 newer7 评论(8) 有9653人浏览
关于程序员的一些悖论是:希望别人将注释和文档写得越详细越好,而自己却讨厌写注释和文档;希望别人严格按照编码规范来写代码,而自己有时候却懒得敲几个空格来缩进……你所在的公司是否有统一的编码规范呢?你是否严格执行了呢?

其实编码中的一些小细节会给阅读者或后续的维护者带来很大的方便,比如本文所述的。本文由外刊IT评论翻译自《Give your code some space!》,原文内容如下。

最近在几个不同的团队中发现他们的编码规范中对空格的用法大不相同。这激起了我的好奇心,因为我一直觉得,对于代码格式中的空格的使用,应该有一个大家都公认的最好的习惯。但是在现实开发中,似乎没有出现这样的统一。

现状

首先,我们看看在大多数Java IDE中Java代码的风格习惯。

下面是一个例子:

public class Example {

public static void main(String[] args) {
    int answer = 2 + 4 * 6;
    for (int i = 0; i < 5; i++) {
        doSomething();
    }
    System.out.println("The answer is " + answer);
}

    private static void doSomething() {
        // something
    }
}


请注意,这是Java编程者中和其它类似C语言的语言中最常见的一种风格

在括号内部两边没有留空格。只有当括号前面有关键字for或while等时,空格才会出现在它们之间,但在方法名和其之后的括号间没有空格。然而,在左大括号前总会有空格(这个左大括号一般会出现在一行的最后)。数学操作符总有空格包围。而分号前不会有空格。

如果你经常阅读代码,也许认为这是很自然的安排,但如果你不是一个程序员,可能会认为这些规则太随意,有很多不统一、特例、有待讨论的地方。

请给你的代码留下多一些空间

在我当前的开发项目中,公司里有两个主要的开发团队,一个是Load Test Products(LTP)团队,另一个是Functional Test Products(FTP)团队。两个团队里遵守了一些编码风格习惯,其中对空格的使用都是特别慷慨,就像下面这个代码片段的例子:

public class Example
{

    public static void main( String[] args )
    {
        int answer = 2 + 4 * 6;
        for( int i = 0; i < 5; i++ )
        {
            doSomething();
        }
        System.out.println( "The answer is " + answer );
    }

    private static void doSomething()
    {
        // something
    }

}


这种风格看起来代码的密度更小,而且更有统一性(例如,在左括号前都没有空格,在所有的括号、花括号、中括号的左右内边都有空格)!我并不是说这样比之前的风格更好或更差….只是这样更容易区别单词。代价就是一个屏幕里只能显示更少的代码。

虽然每种编码风格都有各自的优势和缺点,但让我吃惊的是,FTP开发团队最终决定转向使用之前提到的最常见的那种编码风格。他们认为这种转变是值得的,他们甚至还进行过讨论,所以,我相信他们认为这种转变是重要的。他们判断的依据并不是这种比那种好…我认为这主要着眼于什么人习惯这种风格,因为我们的大部分产品都是开源的,这是重要原因,更容易让社群内的程序员捐赠代码。

在我的团队里,LTP团队,我们仍然坚持我们的风格,不打算做任何改变。至少对于我来说,这是一种基于技术考虑的决定:如果另一种编码风格没有体现出任何的优势(我们的这个项目对开源捐赠的需求很少),为什么要转向另一种风格?

规则需要统一

我一直在给开源项目捐赠代码,比如Ceylon编程语言,让我非常吃惊的是,他们完全没有遵守任何的编码风格。你可以用任何你喜欢的风格来写代码。

也许某些被一些公司里大量的编码规范惊吓住的程序员会喜欢这样,但我相信,如果没一套编码规范,你的项目的代码很可能在格式上出现混乱。每个代码捐赠者都会在提交的代码里带入他特有的代码风格,这不奇怪,结果就是所有的代码各式各样,你从下面几行代码里就能看到多种不同的风格:

while (exists cell = iter) {
        if (exists elem = cell.element,
        elem==element) {
            last = cell;
        }
        iter = cell.rest;
    }
}

if (exists cell=last){
    cell.element=replacement;
    return true;
}
assert (0<=index<length);


我主要想提出的问题是:编码风格究竟是不是一种重要的开发制度?它对程序员开发软件的效率有多大影响?

我相信这个问题牵连到另外一个相似的问题:代码的格式影响代码的可读性吗?

代码格式影响代码的可读性

我认为,这个问题非常容易回答!当然会影响。用眼睛逐行扫描一下下面两段代码(从Ceylon项目中选出的),你会很容易感觉到哪个更易读。 – CeylonCreate)?

function validModuleNameChar(Character c)=>c.letter||c.digit||c in ['_','.' ];
if (!trimmedName.empty,
    validModuleNameFirstChar(trimmedName.first else 'X'),
    trimmedName.every(validModuleNameChar),
    !(trimmedName.split('.'.equals,true,false)).containsAny(ceylonKeywords.chain {""})) {
    return trimmedName;
}


function validModuleNameChar( Character c ) => c.letter || c.digit || c in ['_', '.' ];
if ( ! trimmedName.empty,
    validModuleNameFirstChar ( trimmedName.first else 'X' ),
    trimmedName.every ( validModuleNameChar ),
    ! ( trimmedName.split ( '.'.equals, true, false ) ).containsAny ( ceylonKeywords.chain { "" } ) )
{
    return trimmedName;
}


它们的区别也许很小,但如果你整天花大量的时间读大量的代码,这区别就大了。

从普通文字写作中学到的经验

说起代码的可读性,我们也许应该看看人们更普通的阅读文字的能力,这种能力已经发展了几千年,所以,应该会总结出来更好的方案!?

在“普通”的英文中,你可以看出约定俗成的对于空格的用法,而你却看不到作家们讨论他们是否应该在括号周边使用空格的问题!
那么,如果代码像“普通”英文那样编写,会是什么样子?

回到我们上面简单的例子:

function validModuleNameChar( Character c ) => c.letter || c.digit || c in ['_', '.' ];
if ( ! trimmedName.empty,
    validModuleNameFirstChar ( trimmedName.first else 'X' ),
    trimmedName.every ( validModuleNameChar ),
    ! ( trimmedName.split ( '.'.equals, true, false ) ).containsAny ( ceylonKeywords.chain { "" } ) )
{
    return trimmedName;
}


代码里大部分的东西都本普通英文句子一样。你使用括号将某些字词“分组”。你在单词和符号之间使用空格——这里我们发现了一个跟普通编码习惯不一样的地方:我们在调用方法时,方法名和之后的括号间没有空格,对象点操作符后面不留空白。

我可以理解为什么在这些地方没有空格,因为代码里这些括弧或点号表示了一种“拥有”关系,或关联关系。但真的有必要挤压这一点空间来表示这种关系吗?当我们看上面的这个例子代码时不是感觉很清晰吗?

另外一个在普通英文里不存在的东西是嵌套表达…所以,我们有普通英文写作里不会出现的情况。但这不是大问题,只需要在记住一个通用规则:在符号两边加空格。

你是不是感觉上面的代码有些奇怪?我不得不承认,看起来稍微有些不舒服,当我相信这只是我还不习惯。

虽然还不习惯,但我确定这些代码读起来更容易理解。

我可以明确的说,如果所有的代码都遵守这样的习惯,那我们程序员阅读代码的过程将会轻松的多。

结束语

我希望没有程序员会认为遵守一个预先定义的编码规范会让编程变得困难!

首先,所有的IDE都能配置成自动对代码进行格式规范调整,你写代码时可以写的很乱,但最后别忘了使用IDE里的快捷键整理一下代码,然后再提交代码。同样,我估计没有哪个作家会认为我们的写文字的格式太严,限制了他的创作。

幸运的是,我发现当前所有的编码风格、规范里对空格的使用习惯都没有大问题。但多使用一些空格肯定会让代码更清晰易读。

你觉得呢?

来自: 外刊IT评论
2
3
评论 共 8 条 请登录后发表评论
8 楼 freezingsky 2014-06-16 21:59
现在写代码,写法还是比较遵从常见的java规范,再加上现在有统一的formatter,格式化一下,一了百了。
7 楼 Night舞夜 2014-06-16 10:07
1.if(....){

}

2.if(....)
{

}
喜欢第2种
6 楼 ahack 2014-06-13 21:19
最烦别人左大括号换行了
5 楼 arsemilan 2014-06-13 15:09
左括号占一行 是多么丧心病狂的写法
4 楼 truekbcl 2014-06-13 09:14
最讨厌左大括号放在后面不换行。
既然都用缩进来判断块代码了,还非要单独一个右括号换行来碍眼,且浪费空间。
3 楼 jayung 2014-06-11 12:29
最讨厌左大括号还要单独占一行。
我每次写完一个java类,习惯性的ctrl+shift+F,格式化后,非常容易阅读。
2 楼 200cc 2014-06-11 11:08
括号换行...?! 异端!!!
1 楼 diferent 2014-06-09 14:39
处女座

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • SpringBoot中添加拦截器,在拦截器中注入其他类的时候出现空指针异常解决办法

    拦截器代码 /** * * 记录用户轨迹 */ @Component ... * 在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作) */ @Override public voi

  • JAVA实践-TOMCAT启动项目提示的各种异常:空指针异常,未开启服务等

    配置错了,就会提示一堆的空指针异常,以及404问题。按照错误提示去百度,完全找不到解决的方案。 首先,tomcat所对应的servers项目不能关闭 其次,在servers项目中找到server.xml,是否将项目打开了,拉到最后看这...

  • SurfaceView的使用以及空指针异常的处理

    SurfaceView是视图(View)的继承类,这个视图里内嵌了一个专门用于绘制的surface。我们可以控制这个surface的格式和尺寸。SurfaceView控制这个surface绘制的位置。surface类直接继承Object,对应了一块屏幕缓冲区,...

  • SSM异常处理情况之@Autowired自动装配空指针异常。

    @Autowired自动装配空指针异常。 我造成这点的原因是因为,没有启用监听。 测试代码: Controll层: @Controller @RequestMapping(value="/User") public class UserControll { private static Logger log=...

  • 浅谈Java异常处理机制及项目中的的规范处理方法

    一、前言 异常是程序在运行时出现的不正常情况。这个问题按照面向对象思想进行描述,并封装成了对象。...异常就是Java按照面向对象的思想将问题进行对象封装。这样就方便于操作问题以及处理问题。

  • 10万字208道Java经典面试题总结(附答案)

    JDK中包含JRE,JDK中有一个名为jre的目录,里面包含两个文件夹bin和lib,bin就是JVM,lib就是JVM工作所需要的类库。 2、== 和 equals 的区别是什么? 对于基本类型,==比较的是值; 对于引用类型,==比较的是地址...

  • 错误记录 springboot项目中在拦截器里使用redis获取值,出现空指针错误的原因及解决办法

    在写博客项目时,要判断当前用户是否登录或是否已过期,所以实现了一个拦截器,注入redisUtil然后获取redis的用户登录信息,但明明redis中是存在数据的,还是一直获取为空。 出现原因: 拦截器在SpringContext初始化...

  • 掌握P5级Java面试技巧

    红黑树和二叉平衡树的区别,红黑树和B树,B+树的区别,Mysql二大引擎索引底层实现,HashMap在多线程环境中为何出错?ConcurrentHashMap底层实现,CAS,原子引用,ABA问题,volatile,如何解决HashMap出现的OOM问题?...

  • android 中遇到的空指针异常

    异常信息:java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.GridView.setAdapter(android.widget.ListAdapter)' on a null object reference 1、homePageTab = ...

  • CWE-476: NULL Pointer Dereference(空指针间接引用)

    空指针间接引用发生在应用程序间接引用其预期有效但实际为空的指针时,通常会导致崩溃或退出。 扩展描述 空指针间接引用可能在多个弱点发生后发生,如竞争条件和简单程序省略等。 相关视图 与“研究层面”视图...

  • Java中高级面试题总览(一)

     JAVA 中的几种基本数据类型是什么,各自占用多少字节。 数据类型 关键字 内置类 内存占用字节数 布尔型 boolean Boolean 1字节 字符型 char Character 2字节 字节型 byte Byte 1字节 短整型 short Short 2字节 ...

  • Java知识体系最强总结(2021版)

    本人从事Java开发已多年,平时有记录问题解决方案和总结知识点的习惯,整理了一些有关Java的知识体系,这不是最终版,会不定期的更新。也算是记录自己在从事编程工作的成长足迹,通过博客可以促进博主与阅读者的共同...

  • Java语言基础-如何让程序优雅的报错-异常处理

    异常:在Java语言中,将程序执行中发生的不正常的情况称为“异常”(开发过程中的语法错误与逻辑错误不叫异常)。 Java程序在执行中出现的异常分两类: Error:Java虚拟机无法解决的严重问题,例如:JVM内部错误,...

  • Java开发常见异常|错误

    常见异常 空指针异常: NullPointerExeption 类型转换异常:ClassCastException 数组下标越界异常:ArrayIndexOutOfBoundsException 数字格式化异常:NuberFormatException 文件找不到异常:FileNotFoundException ...

  • 中高级Java程序员,你不得不掌握的基本功,挑战20k+

    3.3 Java中super关键字与final关键字3.4 final修饰的对象,有几种初始化方式3.5 Java中方法的重载(Overload)与方法的覆盖(Override)3.6 Java基础知识总结,干货来啦3.7 Java基础面试题干货系列(一)3.8 Java中...

  • Java阿里巴巴代码规范

    1.3 使用equals方法应该注意空指针 1.3.1 反例 1.3.2 正例 2 异常日志 2.1 事务场景中如果异常被被捕获要注意回滚 2.1.1 反例 2.1.2 正例 2.2 不要在 finally 块中使用 return 2.2.1 反例 2.2.2 正例

  • java中常见类型的转换以及方法总结

    1.char和String之间的转换 1.1 char和String的区别 char是表示的是字符,定义的时候用单引号,只能存储一个字符。例如; char=‘d’. String表示的是字符串,定义的...在Java中将String转换为char是非常简单的。 使

  • 2024java面试题(含答案,持续更新中)

    2023java面试题,java常见面试题及答案:SpringMVC、Redis、Shiro、集合、Oracle数据库、SpringBoot、java基础,线程池面试题

  • Java面试题大全(2020版)

    发现网上很多Java面试题都没有答案,所以花了很长时间搜集整理出来了这套Java面试题大全,希望对大家有帮助哈~ 本套Java面试题大全,全的不能再全,哈哈~ 一、Java 基础 1. JDK 和 JRE 有什么区别? JDK:Java ...

  • Java中常见的单词

    abstract (关键字) 抽象 ['.bstr.kt] access vt.访问,存取 ['.kses]‘(n.入口,使用权) algorithm n.算法 ['.lg.riem] annotation [java]代码注释 [.n.u'tei..n] anonymous adj.匿名的[.'n.ni...

Global site tag (gtag.js) - Google Analytics